package mysqlgo

import (

	"fmt"
	"time"
	"sync"
	"github.com/jmoiron/sqlx"
)

//Config is database connection configuration
type Config struct {
	Alias			string
	HostName	string	
	HostPort	string	
	DBName		string
	UserName	string
	Password	string
	Charset		string	
	Prefix		string
	MaxOpenConns 	int
	MaxIdleConns 	int
	MaxLifetime		int	
	Enable			bool
}

func (config *Config) dsnFormat() (string, error) {
	if config.UserName == "" {
		return "", GetError(UsernameNull)
	}
	if config.HostName == "" {
		return "", GetError(HostNameNull)
	}
	if config.HostPort == "" {
		return "", GetError(HostPortNull)
	}
	if config.DBName == "" {
		return "", GetError(DBNameNull)
	}
	if config.Charset == "" {
		config.Charset = "utf8"
	}
	return fmt.Sprintf(
		"%s:%s@(%s:%s)/%s?charset=%s&parseTime=True&loc=Local",
		config.UserName,
		config.Password,
		config.HostName,
		config.HostPort,
		config.DBName,
		config.Charset,
	), nil
}

type dbConfig struct {
	db 				*sqlx.DB
	dsn				string
	maxOpenConns	int
	maxIdleConns	int
	maxLifetime		int
	configMu		sync.RWMutex
	isClose			bool
}

var driverName =  "mysql"

var dbConfigs = make(map[string]*dbConfig, 0)

var dbMu sync.RWMutex

//Connect 连接数据库并验证是否可以Ping
func Connect(configs ...*Config)(err error){

	if !(len(configs) > 0) {
		return GetError(ConfigNull)
	}

	for _, config := range configs {
		
		if config == nil {
			return GetError(ConfigNull)
		}

		if config.Alias == "" {
			return GetError(DBAliasNull)
		}
		
		dsn, err := config.dsnFormat()
		if err != nil {
			return err
		}
		
		db, err := sqlx.Connect(driverName, dsn)
		if err != nil {
			return err
		}

		db.SetMaxOpenConns(config.MaxOpenConns)
		db.SetMaxIdleConns(config.MaxIdleConns)
		if config.MaxLifetime > 0 {
			db.SetConnMaxLifetime(time.Duration(config.MaxLifetime) * time.Second)
		}
		if d, ok := dbConfigs[config.Alias]; ok {
			//存在键值
			d.db.Close()
			dbConfigs[config.Alias] = &dbConfig {
				db : db,
				maxIdleConns : config.MaxIdleConns,
				maxOpenConns : config.MaxOpenConns,
				maxLifetime  : config.MaxLifetime,
				dsn : dsn,
			}
		} else {
			//不存在键值
			dbConfigs[config.Alias] = &dbConfig {
				db : db,
				maxIdleConns : config.MaxIdleConns,
				maxOpenConns : config.MaxOpenConns,
				maxLifetime  : config.MaxLifetime,
				dsn : dsn,
			}
		}
	}

	return nil
}

//DB 获取指定别名的数据库
//如果不传入别名则默认获取别名为"default"的数据库
func DB(alias ...string) *sqlx.DB {
	dbName := "default"
	dbMu.Lock()
	defer dbMu.Unlock()
	if alias != nil {
		for _, value := range alias {
			if dbc, ok := dbConfigs[value]; ok {
				return dbc.db
			}

		}
	}
	if dbc, ok := dbConfigs[dbName]; ok {
		return dbc.db
	}
	return nil
}